package cate.game.role.res.guild.po;

import cate.common.table.d.GDFunc;
import cate.common.table.d.GDGuild;
import cate.common.table.d.GDMail;
import cate.common.table.d.GDOperation;
import cate.common.util.GameResult;
import cate.game.GameBody;
import cate.game.event.guild.GuildMemberAddedEvent;
import cate.game.mail.po.MailBuilder;
import cate.game.role.Role;
import cate.game.role.farm.guildBoss.msg.MyGuildBossDataResp;
import cate.game.role.mail.Mail;
import cate.game.role.res.guild.GuildFuncBase;
import cate.game.role.res.guild.boss.msg.GuildBossDataResp;
import cate.game.role.res.guild.msg.apply.GuildApplyResp;
import cate.game.role.res.guild.po.member.GuildMemberDetailPO;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;


public class GuildApplyPO extends GuildFuncBase {
    @NoteField(value = "公会申请列表")
    public List<GuildApplyDetailPO> list;

    @Override
    public void initialize(GuildPO guild) {
        super.initialize(guild);
        if (list == null) {
            list = new CopyOnWriteArrayList<>();
        }
        checkExpired();
    }

    /**
     * 删除过期的申请
     */
    @JsonIgnore
    private void checkExpired() {
        if (list == null) {
            return;
        }
        list.removeIf(
                a -> (System.currentTimeMillis() - a.applyTime) / (1000 * 60 * 60)
                        >= GDGuild.basic.APPLY_KEEP_HOUR);
    }


    /**
     * 判断申请是否存在
     *
     * @param uid uid
     * @return t/f
     */
    public boolean exist(String uid) {
        for (GuildApplyDetailPO apply : this.list) {
            if (StringUtils.equals(apply.it.uid, uid)) {
                return true;
            }
        }
        return false;
    }


    /**
     * 公会申请信息列表通知
     */
    @JsonIgnore
    public void noticeUpdate(Role role) {
        if(!guildFuncOpenCheck(role)){
            return;
        }
        checkExpired();
        role.sendNow(new GuildApplyResp(this));
    }


    /**
     * 新增申请
     */
    public GameResult<Void> addApply(Role role, GuildApplyDetailPO apply, String guildId) {
        checkExpired();
        GameResult<Void> r = new GameResult<>();
        if (!list.isEmpty()) {
            for (GuildApplyDetailPO po : list) {
                if (StringUtils.equals(po.it.uid, apply.it.uid)) {
                    role.getGame().notice.message(role, 310435, "加入公会申请列表中存在相同的申请信息");
                    return r.fail("加入公会申请列表中存在相同的申请信息");
                }
            }
        }

        if (list.size() >= GDGuild.APPLY_NUM_LIMIT) {
            role.getGame().notice.message(role, 310436, "当前公会申请玩家已达上限");
            return r.fail("当前公会申请玩家已达上限");
        }

        // 验证通过添加申请
        list.add(apply);
        // 通知在线的会长和副会长
        funcDependent.guild.member
                .getOnlineRoleByPos(role.getGame(),
                        GDGuild.position.PRESIDENT,
                        GDGuild.position.VICE_PRESIDENT,
                        GDGuild.position.PRESBYTER)
                .forEach(this::noticeUpdate);
        return r.success();
    }


    /**
     * 处理申请执行操作
     *
     * @param role      处理者
     * @param applicant 申请者
     * @param confirm   是否同意入会
     */
    public void handleJoinExe(Role role, Role applicant, boolean confirm) {
        Mail m;
        GuildPO guild = getFuncDependent().getGuild();
        List<Object> params = new ArrayList<>();
        params.add(guild.basic.guildName);

        if (confirm) {
            // 添加成员
            EcResult add_r = guild.member.addMember(applicant);
            if (!add_r.ok()) {
                role.getGame().notice.message(role, add_r.message);
                return;
            }
            // 给操作者通知成员列表
            if (role != applicant) {
                guild.member.noticeUpdate(role);
            }
            // 删除申请者身上的入会申请和所有公会里关于他的申请
            applicant.getRes().guild.apply.deleteAllApply();
            // 给申请者发邮件
            m =
                    new MailBuilder()
                            .setContentId(GDMail.Tid.JOIN_GUILD_SUCCESS)
                            .setParamList(params)
                            .setOperation(GDOperation.NULL)
                            .build();
            // 记录日志
            guild.member.memberLog.addLog(role.getGame(),
                    new GuildLogDetailPO(GDGuild.log.NEW_MEMBER_JOIN, applicant.getBase().name));
            // 公会频道
            List<Object> paramList = new ArrayList<>();
            paramList.add(applicant.getBase().name);
            if (role.getGame().role.findOnline(applicant.getUid()) != null) {
                applicant.sendNow(new GuildBossDataResp(applicant.getRes().guild.getGuild().boss));
                applicant.sendNow(new MyGuildBossDataResp(applicant));
                applicant.getFarm().guildFairyland.noticeUpdate();
            }
//            ChatFacade.sendGuildAsSystemMember(role.getGame(),
//                    guild.uid, GDNotice.TextId.NEW_MEMBER_JOIN, paramList);

            // 如果会长不存在
            GuildMemberDetailPO president = guild.member.getMember(guild.basic.presidentId);
            if (president == null || president.it.unreal) {
                guild.member.autoChangePresident(role);
            }
            applicant.getHistory().action.hadAGuild();
            //战力更新
            if (applicant.getStatus().isOnline()){
                applicant.getBase().updatePower();
            }

            GuildMemberAddedEvent memberAddEvent = new GuildMemberAddedEvent(applicant);
            memberAddEvent.setGuild(guild);
            publishEvent(guild.game, memberAddEvent);
        } else {
            // 从公会申请列表中删除该申请
            this.clearSingleApply(role.getGame(), applicant.getBase().uid);
            m =
                    new MailBuilder()
                            .setContentId(GDMail.Tid.JOIN_GUILD_FAIL)
                            .setParamList(params)
                            .setOperation(GDOperation.NULL)
                            .build();
            applicant.getRes().guild.apply.deleteApply(guild.uid);
        }
        // 发送处理结果的邮件
        applicant.getMail().add(m);
    }


    /**
     * 删除某个玩家的申请
     */
    @JsonIgnore
    public void clearSingleApply(GameBody game, String uid) {
        list.removeIf(a -> StringUtils.equals(a.it.uid, uid));
        GuildPO guild = getFuncDependent().getGuild();
        guild.member
                .getOnlineRoleByPos(game,
                        GDGuild.position.PRESIDENT,
                        GDGuild.position.VICE_PRESIDENT,
                        GDGuild.position.PRESBYTER)
                .forEach(this::noticeUpdate);
    }

    /**
     * 删除某个玩家的申请
     */
    @JsonIgnore
    public void clearAllApply(GameBody game) {
        if(!guildFuncOpenCheck()){
            return;
        }
        list.clear();
        GuildPO guild = getFuncDependent().getGuild();
        guild.member
                .getOnlineRoleByPos(game,
                        GDGuild.position.PRESIDENT,
                        GDGuild.position.VICE_PRESIDENT,
                        GDGuild.position.PRESBYTER)
                .forEach(this::noticeUpdate);
    }

    /**
     * 处理入会申请信息
     */
    public void handleJoin(Role role, String idHex, boolean confirm) {
        if (!guildFuncOpenCheck(role)) {
            return;
        }
        byte pos = role.getRes().guild.getPos();
        if (pos == GDGuild.position.MEMBER) {
            role.getGame().notice.message(role, 310437, "只有公会管理者可以处理公会申请");
            return;
        }
        if (role.getRes().guild.getGuild().member.getMember(idHex) != null) {
            role.getGame().notice.message(role, 310438, "该成员已经加入公会");
            return;
        }
        boolean exist = exist(idHex);
        if (!exist) {
            role.getGame().notice.message(role, 310439, "公会申请列表中不存在该成员");
            return;
        }
        Role applicant = role.getGame().role.getRole(idHex);
        if (applicant == null || applicant.getRes().guild.checkGuild().ok()) {
            role.getGame().notice.message(role, 310440, "该玩家已加入其他公会");
            // 从公会申请列表中删除该申请
            this.clearSingleApply(role.getGame(), idHex);
            return;
        }
        // 入会操作
        handleJoinExe(role, applicant, confirm);
    }

    @Override
    public int getFuncId() {
        return GDFunc.GuildFunc.MEMBER;
    }
}
